package cc.tuhaolicai.mt.user.mobile.tool;

import com.google.common.collect.Maps;
import org.asyou.mongo.annotation.Collection;
import pro.tools.data.text.ToolStr;
import redis.clients.jedis.Jedis;

import java.lang.reflect.Field;
import java.util.List;
import java.util.Map;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 通用获取id
 *
 * @author chenli
 * @create 2017-07-20
 */
public final class ToolGen {

    private static final Map<String, ReentrantLock> LOCK_MAP = Maps.newConcurrentMap();

    private static ReentrantLock getLock(String key) {
        ReentrantLock lock = LOCK_MAP.get(key);
        if (lock != null) {
            return lock;
        } else {
            lock = new ReentrantLock();
            ReentrantLock previousLock = LOCK_MAP.putIfAbsent(key, lock);
            return previousLock == null ? lock : previousLock;
        }
    }

    public static String getModelName(Class<?> modelClass){
        Collection annotation = modelClass.getAnnotation(Collection.class);
        if(annotation == null){
            return modelClass.getSimpleName();
        }
        String name = annotation.name();
        if(ToolStr.isBlank(name)){
            return modelClass.getSimpleName();
        }
        return name;
    }

    /**
     * 全局通用的生成ID方法
     *
     * @param modelClass：
     * @return
     */
    public static Long genId(Class<?> modelClass,String idStr) {
        String key = getModelName(modelClass);
        key = "ID:"+key;
        ReentrantLock lock = getLock(key);
        if (lock != null) {
            lock.lock();
            try (Jedis jedis = ToolRedis.Factory.getJedis()) {
                //防止redis缓存已消失
                String oldId = jedis.get(key);
                if(ToolStr.isBlank(oldId)){
                    List<Object> list = ToolMongo.Factory.getAdapter().collection(key).findMany("{}").sort("{" + idStr + ":-1}").skip(0).limit(1).as(modelClass);
                    if(list != null && list.size() >0){
                        Object model = list.get(0);
                        Field listOneField;//获取该属性
                        try {
                            listOneField = modelClass.getDeclaredField(idStr);
                            listOneField.setAccessible(true);//可编辑
                            Object value = listOneField.get(model);//list中对象该属性值
                            listOneField.setAccessible(false);
                            ToolRedis.setString(key,String.valueOf(value));
                        } catch (NoSuchFieldException | IllegalAccessException e) {
                            e.printStackTrace();
                            throw new RuntimeException("redis该id缓存被清楚,重新存入redis缓存失败");
                        }
                    }
                }

                Long id = jedis.incr(key);
                if (id != null) {
                    return id;
                }
            } finally {
                lock.unlock();
            }
        }
        try {
            Thread.sleep(5000L);
            return genId(modelClass,idStr);
        } catch (InterruptedException e) {
            e.printStackTrace();
            throw new RuntimeException("获取生成id递归异常");
        }
    }

}